/** * Copyright (c) 2002-2012 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.perftest.enterprise.ccheck; import static org.neo4j.perftest.enterprise.util.Configuration.settingsOf; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Map; import java.util.TreeMap; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.util.DefaultPrettyPrinter; import org.neo4j.kernel.configuration.Config; import org.neo4j.perftest.enterprise.generator.DataGenerator; import org.neo4j.perftest.enterprise.util.Configuration; import org.neo4j.perftest.enterprise.util.Setting; class JsonReportWriter implements TimingProgress.Visitor { private final File target; private JsonGenerator json; private boolean writeRecordsPerSecond = true; private final Configuration configuration; private final Config tuningConfiguration; JsonReportWriter( Configuration configuration, Config tuningConfiguration ) { this.configuration = configuration; this.tuningConfiguration = tuningConfiguration; target = new File( configuration.get( ConsistencyPerformanceCheck.report_file ) ); } @Override public void beginTimingProgress( long totalElementCount, long totalTimeNanos ) throws IOException { ensureOpen( false ); json = new JsonFactory().configure( JsonGenerator.Feature.AUTO_CLOSE_TARGET, true ) .createJsonGenerator( new FileWriter( target ) ); json.setPrettyPrinter( new DefaultPrettyPrinter() ); json.writeStartObject(); { json.writeFieldName( "config" ); json.writeStartObject(); emitConfiguration(); json.writeEndObject(); } { json.writeFieldName( "tuningConfig" ); json.writeStartObject(); emitTuningConfiguration(); json.writeEndObject(); } { json.writeFieldName( "total" ); json.writeStartObject(); emitTime( totalElementCount, totalTimeNanos ); json.writeEndObject(); } json.writeFieldName( "phases" ); json.writeStartArray(); } private void emitConfiguration() throws IOException { for ( Setting<?> setting : settingsOf( DataGenerator.class, ConsistencyPerformanceCheck.class ) ) { emitSetting( setting ); } } private <T> void emitSetting( Setting<T> setting ) throws IOException { json.writeStringField( setting.name(), setting.asString( configuration.get( setting ) ) ); } private void emitTuningConfiguration() throws IOException { Map<String,String> params = new TreeMap<String,String>(tuningConfiguration.getParams()); for ( String key : params.keySet() ) { json.writeStringField( key, params.get( key ) ); } } @Override public void phaseTimingProgress( String phase, long elementCount, long timeNanos ) throws IOException { ensureOpen( true ); json.writeStartObject(); json.writeStringField( "name", phase ); emitTime( elementCount, timeNanos ); json.writeEndObject(); } private void emitTime( long elementCount, long timeNanos ) throws IOException { json.writeNumberField( "elementCount", elementCount ); double millis = TimeLogger.nanosToMillis( timeNanos ); json.writeNumberField( "time", millis ); if ( writeRecordsPerSecond ) { json.writeNumberField( "recordsPerSecond", (elementCount * 1000.0) / millis ); } } @Override public void endTimingProgress() throws IOException { ensureOpen( true ); json.writeEndArray(); json.writeEndObject(); json.close(); } private void ensureOpen( boolean open ) throws IOException { if ( (json == null) == open ) { throw new IOException( new IllegalStateException( String.format( "Writing %s started.", open ? "not" : "already" ) ) ); } } }